﻿//////////////////////////////////////////////////////////////////
//
// AuditLogImpl.cs
//
// Copyright (c) 2012 Dan Pike.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Globalization;
using log4net.Core;
using log4net.Repository;
using log4net.Util;

namespace log4net.Ext.Audit
{
   public class AuditLogImpl : LoggerWrapperImpl, IAuditLog
   {
      public readonly static Level defaultLevelAudit_ = new Level(5000, "AUDIT");
      public static Level levelAudit;
      public static Level levelDebug;
      public static Level levelInfo;
      public static Level levelWarn;
      public static Level levelError;
      public static Level levelFatal;
      private bool enabled_ = true;

      public AuditLogImpl(ILogger logger)
         : base(logger)
      {
         // Listen for changes to the repository
         logger.Repository.ConfigurationChanged += new log4net.Repository.LoggerRepositoryConfigurationChangedEventHandler(Repository_ConfigurationChanged);
         ReloadLevels(logger.Repository);
      }

      void Repository_ConfigurationChanged(object sender, EventArgs e)
      {
         ILoggerRepository repository = sender as ILoggerRepository;
         if (null != repository)
         {
            ReloadLevels(repository);
         }
      }

      protected virtual void ReloadLevels(log4net.Repository.ILoggerRepository repository)
      {
         LevelMap levelMap = repository.LevelMap;
         levelAudit = levelMap.LookupWithDefault(defaultLevelAudit_);
         levelDebug = levelMap.LookupWithDefault(Level.Debug);
         levelInfo = levelMap.LookupWithDefault(Level.Info);
         levelWarn = levelMap.LookupWithDefault(Level.Warn);
         levelError = levelMap.LookupWithDefault(Level.Error);
         levelFatal = levelMap.LookupWithDefault(Level.Fatal);
      }

      public void Audit(object message)
      {
         if (IsAuditEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelAudit, message, null);
         }
      }

      public void Audit(object message, System.Exception t)
      {
         if (IsAuditEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelAudit, message, t);
         }
      }

      public void AuditFormat(string format, object arg0)
      {
         if (IsAuditEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelAudit,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null);
         }
      }

      public void AuditFormat(string format, object arg0, object arg1)
      {
         if (IsAuditEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelAudit,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null);
         }
      }

      public void AuditFormat(string format, object arg0, object arg1, object arg2)
      {
         if (IsAuditEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelAudit,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null);
         }
      }

      public void AuditFormat(string format, params object[] args)
      {
         if (IsAuditEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelAudit,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
         }
      }

      public void AuditFormat(IFormatProvider provider, string format, params object[] args)
      {
         if (IsAuditEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelAudit, new SystemStringFormat(provider, format, args), null);
         }
      }

      public bool IsAuditEnabled
      {
         get
         {
            return enabled_ && Logger.IsEnabledFor(levelAudit);
         }
         set
         {
            if (enabled_ != value)
            {
               if (enabled_)
               {
                  // Output the message before we disable audits!
                  Audit("AUDIT HAS BEEN PROHIBITED");
               }
               enabled_ = value;
               if (enabled_)
               {
                  // Output the message after we reenable audits!
                  Audit("AUDIT HAS BEEN ENABLED");
               }
            }
         }
      }

      public void Debug(object message)
      {
         if (IsDebugEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelDebug, message, null);
         }
      }

      public void Debug(object message, System.Exception t)
      {
         if (IsDebugEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelDebug, message, t);
         }
      }

      public void DebugFormat(string format, object arg0)
      {
         if (IsDebugEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelDebug,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null);
         }
      }

      public void DebugFormat(string format, object arg0, object arg1)
      {
         if (IsDebugEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelDebug,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null);
         }
      }

      public void DebugFormat(string format, object arg0, object arg1, object arg2)
      {
         if (IsDebugEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelDebug,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null);
         }
      }

      public void DebugFormat(string format, params object[] args)
      {
         if (IsDebugEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelDebug,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
         }
      }

      public void DebugFormat(IFormatProvider provider, string format, params object[] args)
      {
         if (IsDebugEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelDebug, new SystemStringFormat(provider, format, args), null);
         }
      }

      public bool IsDebugEnabled
      {
         get
         {
            return Logger.IsEnabledFor(levelDebug);
         }
      }

      public void Info(object message)
      {
         if (IsInfoEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelInfo, message, null);
         }
      }

      public void Info(object message, System.Exception t)
      {
         if (IsInfoEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelInfo, message, t);
         }
      }

      public void InfoFormat(string format, object arg0)
      {
         if (IsInfoEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelInfo,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null);
         }
      }

      public void InfoFormat(string format, object arg0, object arg1)
      {
         if (IsInfoEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelInfo,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null);
         }
      }

      public void InfoFormat(string format, object arg0, object arg1, object arg2)
      {
         if (IsInfoEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelInfo,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null);
         }
      }

      public void InfoFormat(string format, params object[] args)
      {
         if (IsInfoEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelInfo,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
         }
      }

      public void InfoFormat(IFormatProvider provider, string format, params object[] args)
      {
         if (IsInfoEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelInfo, new SystemStringFormat(provider, format, args), null);
         }
      }

      public bool IsInfoEnabled
      {
         get
         {
            return Logger.IsEnabledFor(levelInfo);
         }
      }

      public void Warn(object message)
      {
         if (IsWarnEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelWarn, message, null);
         }
      }

      public void Warn(object message, System.Exception t)
      {
         if (IsWarnEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelWarn, message, t);
         }
      }

      public void WarnFormat(string format, object arg0)
      {
         if (IsWarnEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelWarn,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null);
         }
      }

      public void WarnFormat(string format, object arg0, object arg1)
      {
         if (IsWarnEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelWarn,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null);
         }
      }

      public void WarnFormat(string format, object arg0, object arg1, object arg2)
      {
         if (IsWarnEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelWarn,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null);
         }
      }

      public void WarnFormat(string format, params object[] args)
      {
         if (IsWarnEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelWarn,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
         }
      }

      public void WarnFormat(IFormatProvider provider, string format, params object[] args)
      {
         if (IsWarnEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelWarn, new SystemStringFormat(provider, format, args), null);
         }
      }

      public bool IsWarnEnabled
      {
         get
         {
            return Logger.IsEnabledFor(levelWarn);
         }
      }

      public void Error(object message)
      {
         if (IsErrorEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelError, message, null);
         }
      }

      public void Error(object message, System.Exception t)
      {
         if (IsErrorEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelError, message, t);
         }
      }

      public void ErrorFormat(string format, object arg0)
      {
         if (IsErrorEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelError,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null);
         }
      }

      public void ErrorFormat(string format, object arg0, object arg1)
      {
         if (IsErrorEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelError,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null);
         }
      }

      public void ErrorFormat(string format, object arg0, object arg1, object arg2)
      {
         if (IsErrorEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelError,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null);
         }
      }

      public void ErrorFormat(string format, params object[] args)
      {
         if (IsErrorEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelError,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
         }
      }

      public void ErrorFormat(IFormatProvider provider, string format, params object[] args)
      {
         if (IsErrorEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelError, new SystemStringFormat(provider, format, args), null);
         }
      }

      public bool IsErrorEnabled
      {
         get
         {
            return Logger.IsEnabledFor(levelError);
         }
      }

      public void Fatal(object message)
      {
         if (IsFatalEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelFatal, message, null);
         }
      }

      public void Fatal(object message, System.Exception t)
      {
         if (IsFatalEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelFatal, message, t);
         }
      }

      public void FatalFormat(string format, object arg0)
      {
         if (IsFatalEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelFatal,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0 }), null);
         }
      }

      public void FatalFormat(string format, object arg0, object arg1)
      {
         if (IsFatalEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelFatal,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1 }), null);
         }
      }

      public void FatalFormat(string format, object arg0, object arg1, object arg2)
      {
         if (IsFatalEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelFatal,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, new object[] { arg0, arg1, arg2 }), null);
         }
      }

      public void FatalFormat(string format, params object[] args)
      {
         if (IsFatalEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelFatal,
               new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
         }
      }

      public void FatalFormat(IFormatProvider provider, string format, params object[] args)
      {
         if (IsFatalEnabled)
         {
            Logger.Log(AuditLogManager.ThisDeclaringType, levelFatal, new SystemStringFormat(provider, format, args), null);
         }
      }

      public bool IsFatalEnabled
      {
         get
         {
            return Logger.IsEnabledFor(levelFatal);
         }
      }
   }
}
